package com.lap.auth.application.authorization;

import com.lap.auth.application.api.ApiPermissionQueryService;
import com.lap.auth.application.authorization.assembler.AuthorAssembler;
import com.lap.auth.application.authorization.dto.*;
import com.lap.auth.application.authorization.dto.ApiDto;
import com.lap.auth.application.menu.MenuPermissionQueryService;
import com.lap.auth.application.role.RoleDataScopeQueryService;
import com.lap.auth.application.role.dto.RoleDataScopeDto;
import com.lap.auth.domain.api.Api;
import com.lap.auth.domain.menu.Menu;
import com.lap.auth.domain.shared.errors.UserError;
import com.lap.auth.domain.user.User;
import com.lap.auth.domain.user.repository.UserRoleRepository;
import com.lap.auth.domain.user.service.UserValidator;
import com.lap.context.starter.helper.UserHelper;
import com.lap.framework.exception.BizException;
import java.util.Date;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

@RequiredArgsConstructor
@Service
public class AuthorQueryService {

  private final AuthorAssembler assembler;
  private final UserValidator userValidator;
  private final ApiPermissionQueryService apiPermissionQueryService;
  private final RoleDataScopeQueryService roleDataScopeQueryService;
  private final MenuPermissionQueryService menuPermissionQueryService;
  private final UserRoleRepository userRoleRepository;

  public UserInfoDto getUserInfo() {
    User user = userValidator.assertUserExists(UserHelper.getUserId());
    List<Integer> roleIds = userRoleRepository.findByUserId(UserHelper.getUserId());
    if (roleIds.isEmpty()) {
      throw BizException.newBiz(UserError.NO_AUTH);
    }

    List<String> opList = menuPermissionQueryService.getOptionsByRoles(roleIds);
    return UserInfoDto.builder()
        .userId(user.getId())
        .username(user.getFullName() + "(" + user.getUsername() + ")")
        .authBtnList(opList)
        .time(new Date())
        .photo(
            "https://img2.baidu.com/it/u=1978192862,2048448374&fm=253&fmt=auto&app=138&f=JPEG?w=504&h=500")
        .build();
  }

  public List<MenuViewDto> getMenus() {
    List<Integer> roleIds = userRoleRepository.findByUserId(UserHelper.getUserId());
    if (roleIds.isEmpty()) {
      throw BizException.newBiz(UserError.NO_AUTH);
    }

    List<Menu> menuList = menuPermissionQueryService.getMenusByRoles(roleIds);
    List<MenuViewDto> sources = assembler.toMenuDtoList(menuList);
    return assembler.convertToTree(sources);
  }

  /**
   * 提供接口给网关验证
   *
   * <ol>
   *   <li>性能:需要缓存
   *   <li>用户->角色->接口权限->数据权限
   * </ol>
   *
   * @return 权限
   */
  public PermissionDto getPermission() {
    List<Integer> roleIds = userRoleRepository.findByUserId(UserHelper.getUserId());
    if (roleIds.isEmpty()) {
      throw BizException.newBiz(UserError.NO_AUTH);
    }

    // 接口权限
    List<Api> apiSources = apiPermissionQueryService.getInsideApis(roleIds);
    List<ApiDto> apiList = assembler.toDtoList(apiSources);

    // 数据权限
    RoleDataScopeDto roleDataScopeDto = roleDataScopeQueryService.aggregateByRoleIds(roleIds);
    DataScopeDto dataScopeDto = assembler.toDataScopeDto(roleDataScopeDto);

    return PermissionDto.builder().apiList(apiList).dataScope(dataScopeDto).build();
  }
}
